package org.gwc.advice;

import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 增强类的内部要存储增强代码
 * 1、定义方法存储增强代码
 *      具体定义几个方法，根据插入的位置决定
 * 2、使用注解配置，指定插入目标方法的位置
 *      前置 @Before
 *      后置 @AfterReturning
 *      异常 @AfterThrowing
 *      最后 @After
 *      环绕 @Around
 *
 *      try{
 *          前置
 *          目标方法
 *          后置
 *      }catch(){
 *          异常
 *      }finally{
 *          最后
 *      }
 * 3、配置切点表达式
 *      作用在哪个类的哪个方法
 * 4、补全注解
 *      @Component // 加入到ioc容器中
 *      @Aspect  // 配置切面
 * 5、开启aspect的注解支持
 */

/**
 * 切点表达式
 * 固定语法：execution(1 2 3.4.5(6))
 * 1、访问修饰符
 *      public / private
 * 2、方法的返回参数类型
 *      String int void
 * 如果不考虑访问修饰符和返回值，这两位整合成一起写*,两个是一起的，不能单独出现 * String
 * 3、包的位置
 *      具体包：org.gwc.service.impl
 *      单层模糊：org.gwc.service.*
 *      多层模糊：org..impl
 *      细节：不能以..开头
 *      找所有的impl包：com..impl 不能写成 ..impl,应写成 *..impl
 * 4、类的名称
 *      具体：CalculatorPureImpl
 *      模糊：*
 *      部分模糊：*impl
 * 5、方法名 语法和类名一致
 * 6、形参列表
 *      没有参数：()
 *      有具体参数：(String) (String int)
 *      模糊参数：(..) 有没有参数都可以，有多个也可以
 *      部分模糊：(String..) String 为第一个参数
 *              (..int) 最后一个参数为int
 *
 *
 */

/**
 * 切点表达式的提取和复用
 * 1、当前类中提取
 *      定义一个空方法
 *      注解@PointCut
 *      增强注解中引用切点表达式的方法即可 直接调用方法
 * 2、创建一个存储切点的类
 *      单独维护切点表达式
 *      其他类的切点方法 类的全限定符号.方法名()
 */
@Aspect  // 代表切面
@Component // 加入到ioc容器中
@Order(5) // 切面优先级，值越低，优先级越高
public class LogAdvice {

    @Pointcut("execution(* org.gwc.service.impl.*.*(..))")
    public void pc(){

    }

    @Before("pc()")
    public void start(){
        System.out.println("方法开始了");
    }
    @AfterReturning("org.gwc.advice.MyPointCut.myPC()")
    public void afterReturning(){
        System.out.println("方法结束了");
    }
    @AfterThrowing("execution(* org.gwc.service.impl.*.*(..))")
    public void afterThrowing(){
        System.out.println("方法异常了");
    }
}
